import { useData, useReqIp, useWeapp } from '@sker/runtime'
import { useTransaction, generateRandomString, HttpError, encryptPassword } from '@sker/core';
import { z } from 'zod';
import dayjs from 'dayjs';
import { WxMGroup, WxMember, WxToken } from '@sker/entities';

export default async () => {
    const input = z.object({
        code: z.string(),
        parent_code: z.optional(z.string())
    })
    const body = input.parse(useData())
    const res = await useTransaction(async (m) => {
        const app = await useWeapp();
        const { openid, unionid } = await app.codeToSession(body.code)
        if (!openid)
            throw new HttpError(`获取openid失败，请联系管理员检查配置是否正确`);
        let member = await m.findOne(WxMember, { where: { openid }, select: { id: true } });
        if (unionid) {
            member = await m.findOne(WxMember, { where: { unionid }, select: { id: true } });
        }
        const password = generateRandomString(8)
        const salt = generateRandomString(8)
        const saltPassword = await encryptPassword(password, salt)
        const wxGroup = await m.findOne(WxMGroup, { where: { is_default: true } })
        if (!wxGroup) throw new HttpError(`未设置默认会员组`)
        if (!member) {
            const { id } = await m.save(WxMember, {
                openid,
                unionid,
                appid: app.getAppid(),
                permissions: {},
                password: saltPassword,
                salt: salt,
                status: true,
                online: true,
                code: body.parent_code || '',
                group_id: wxGroup.id,
            })
            member = { id } as any;
        }
        const ip = useReqIp();
        const token = generateRandomString(64)
        const refresh_token = generateRandomString(64);
        const expires_in = dayjs().add(30, 'day').toDate();
        const refresh_token_expires_in = dayjs().add(365, 'day').toDate();
        const wxToken = await m.findOne(WxToken, { where: { member_id: member.id }, select: { id: true } })
        if (wxToken) {
            await m.update(WxToken, wxToken.id, { status: `1`, ip, token, member_id: member.id, refresh_token, expires_in, refresh_token_expires_in, session: member as any })
        }
        await m.save(WxToken, {
            status: `1`,
            ip,
            token,
            member_id: member.id,
            refresh_token,
            expires_in,
            refresh_token_expires_in,
            session: member as any
        })
        return {
            token,
            refresh_token,
            expires_in,
            refresh_token_expires_in
        }
    })
    return res;
}